package com.lzp.java.concurrent.threadcore.background;

/**
 * 使用工厂方法解决构造器注册监听器逸出的问题
 * <p>
 * 改进之前构造器中包含了匿名内部类创建监听器，注册监听器，循环，赋值
 * 由于监听器注册的时机不当，导致count还未被赋值100，就打印了JVM初始值0
 * 措施：采用工厂方法，在构造器准备好之后，才注册监听器
 * 注意：此时构造器私有
 *
 * @author lzp
 * @date 2020/02/18
 */
public class MultiThreadError5Improved {

    int count;

    private EventListener eventListener;

    private MultiThreadError5Improved(MySource source) {
        // 初始化监听器
        eventListener = new EventListener() {
            @Override
            public void onEvent(Event e) {
                System.out.println("\n我得到的数字是" + count);
            }
        };
        for (int i = 0; i < 10000; i++) {
            System.out.print(i);
        }
        count = 100;
    }

    public static MultiThreadError5Improved getInstance(MySource source) {
        // 完全构造初始化
        MultiThreadError5Improved safeInstance = new MultiThreadError5Improved(source);
        // 然后注册监听器
        source.registerListener(safeInstance.eventListener);
        return safeInstance;
    }

    public static void main(String[] args) {
        MySource mySource = new MySource();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 休眠10ms，触发事件
                mySource.eventCome(new Event() {
                });
            }
        }).start();
        MultiThreadError5Improved multiThreadsError5 = getInstance(mySource);
    }

    /**
     * 观察者模式
     */
    static class MySource {

        private EventListener listener;

        void registerListener(EventListener eventListener) {
            this.listener = eventListener;
        }

        void eventCome(Event e) {
            if (listener != null) {
                listener.onEvent(e);
            } else {
                System.out.println("还未初始化完毕");
            }
        }

    }

    /**
     * 事件监听器
     */
    @FunctionalInterface
    interface EventListener {
        void onEvent(Event e);
    }

    /**
     * 事件接口
     */
    interface Event {

    }
}
